package drds.plus.executor.cursor.cursor.impl.result_cursor;


import drds.plus.executor.ExecuteContext;
import drds.plus.executor.cursor.cursor.impl.DuplicateValueRowDataLinkedList;
import drds.plus.executor.cursor.cursor_metadata.CursorMetaData;
import drds.plus.executor.cursor.cursor_metadata.CursorMetaDataImpl;
import drds.plus.executor.record_codec.record.KeyValueRecordPair;
import drds.plus.executor.record_codec.record.Record;
import drds.plus.executor.row_values.ArrayRowValues;
import drds.plus.executor.row_values.RowValues;
import drds.plus.sql_process.abstract_syntax_tree.ObjectCreateFactory;
import drds.plus.sql_process.abstract_syntax_tree.configuration.ColumnMetaData;
import drds.plus.sql_process.abstract_syntax_tree.expression.item.column.Column;
import drds.plus.sql_process.type.Type;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

public class RowDataListResultCursor extends ResultCursor {

    private final String tableName;
    private List<RowValues> rowDataList = new ArrayList();
    private Iterator<RowValues> rowDataIterator = null;
    private CursorMetaData cursorMetaData;
    private List<ColumnMetaData> columnMetaDataList = new ArrayList();
    private RowValues currentRowData;
    private boolean closed = false;

    public RowDataListResultCursor(String tableName, ExecuteContext executeContext) {
        super(executeContext);
        this.tableName = tableName;
        this.originalSelectColumns = new ArrayList();
    }

    public void addColumn(String columnName, Type type) {
        ColumnMetaData columnMetaData = new ColumnMetaData(this.tableName, columnName, type, null, true, false);
        columnMetaDataList.add(columnMetaData);

        Column column = ObjectCreateFactory.createColumn();
        column.setTableName(this.tableName);
        column.setColumnName(columnName);
        column.setType(type);
        originalSelectColumns.add(column);
    }

    public void addRowData(Object[] values) {
        ArrayRowValues arrayRowData = new ArrayRowValues(this.cursorMetaData, values);
        rowDataList.add(arrayRowData);
    }

    public boolean skipTo(Record keyRecord) throws RuntimeException {
        return false;
    }

    public boolean skipTo(KeyValueRecordPair keyKeyValueRecordPair) throws RuntimeException {
        return false;
    }

    public RowValues current() throws RuntimeException {
        return this.currentRowData;
    }

    public RowValues next() throws RuntimeException {
        if (rowDataIterator == null) {
            rowDataIterator = rowDataList.iterator();
        }
        if (rowDataIterator.hasNext()) {
            currentRowData = rowDataIterator.next();
            return currentRowData;
        }
        currentRowData = null;
        return null;
    }

    public RowValues prev() throws RuntimeException {
        throw new UnsupportedOperationException();
    }

    public RowValues first() throws RuntimeException {
        if (rowDataList.isEmpty())
            return null;
        return rowDataList.get(0);
    }

    public void beforeFirst() throws RuntimeException {
        rowDataIterator = rowDataList.iterator();
        currentRowData = null;

    }

    public RowValues last() throws RuntimeException {
        if (rowDataList.isEmpty())
            return null;
        return rowDataList.get(rowDataList.size() - 1);
    }

    public List<RuntimeException> close(List<RuntimeException> exceptions) {
        this.closed = true;
        if (exceptions == null)
            exceptions = new ArrayList();
        return exceptions;
    }

    public boolean delete() throws RuntimeException {
        throw new UnsupportedOperationException();
    }

    public RowValues getNextDuplicateValueRowData() throws RuntimeException {
        throw new UnsupportedOperationException();
    }

    public void put(Record key, Record value) throws RuntimeException {
        throw new UnsupportedOperationException();
    }

    public Map<Record, DuplicateValueRowDataLinkedList> mgetRecordToDuplicateValueRowDataLinkedListMap(List<Record> keyRecordList, boolean prefixMatch, boolean keyFilterOrValueFilter) throws RuntimeException {
        throw new UnsupportedOperationException();
    }

    public List<DuplicateValueRowDataLinkedList> mgetDuplicateValueRowDataLinkedListList(List<Record> keyRecordList, boolean prefixMatch, boolean keyFilterOrValueFilter) throws RuntimeException {
        throw new UnsupportedOperationException();
    }

    public boolean isDone() {
        return true;
    }

    public List<ColumnMetaData> getColumnMetaDataList() throws RuntimeException {
        return columnMetaDataList;
    }

    public void initMeta() {
        this.cursorMetaData = CursorMetaDataImpl.buildCursorMetaData(columnMetaDataList);

    }

    public boolean isClosed() {
        return this.closed;
    }

    public String toStringWithInden(int inden) {
        StringBuilder sb = new StringBuilder();
        sb.append("result : ").append("\n");
        sb.append(this.rowDataList);
        return sb.toString();
    }
}
